package yagwl.service.util.svc;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;

import yagwl.service.util.db.DaoContext;
import yagwl.service.util.db.EMF;

// GWT-RPC creates this once for each service class and reuses;
// hence not thread-safe
// all member variables, except service class (delegate) should be static
public class ServiceInvocationHandler implements InvocationHandler {
  private static final Logger log = Logger
      .getLogger(ServiceInvocationHandler.class.getName());

  private Object delegate;

  public ServiceInvocationHandler(Object delegate) {
    this.delegate = delegate;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
    long startTime = System.currentTimeMillis();
    Context ctx = null;
    DaoContext dctx = null;
    EntityManager em = null;
    try {
      if (log.isLoggable(Level.INFO)) {
        log.info("-----------------------------------------------------------");
        log.info("Calling " + method + " at " + new Date(startTime));
      }
      em = EMF.get().createEntityManager();
      dctx = new DaoContext(em);
      ctx = Context.getCurrentInstance();
      ctx.setDaoContext(dctx);
      Object result = method.invoke(delegate, args);
      return result;
    } catch (InvocationTargetException e) {
      throw e.getTargetException();
    } finally {
      if (em != null)
        em.close();
      em = null;
      dctx = null;
      ctx = null;
      if (log.isLoggable(Level.INFO)) {
        log.info("Called " + method + ", time: "
            + (System.currentTimeMillis() - startTime) + " msec");
        log.info("-----------------------------------------------------------");
      }
    }
  }
}
